package cn.jbt.api.admin.service.impl;

import cn.jbt.api.admin.entity.QSysConfig;
import cn.jbt.api.admin.entity.SysConfig;
import cn.jbt.api.admin.filter.LoginInfoAccessContext;
import cn.jbt.api.admin.repository.SysConfigRepository;
import cn.jbt.api.admin.service.ISysConfigService;
import cn.jbt.common.PageQryParam;
import cn.jbt.common.PageQryResult;
import cn.jbt.config.AliyunOssConfig;
import cn.jbt.config.MinioOssConfig;
import cn.jbt.config.PubConfig;
import cn.jbt.config.XxlJobConfig;
import com.alibaba.fastjson.JSON;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

@Service
@Slf4j
@AllArgsConstructor
public class SysConfigServiceImpl implements ISysConfigService {

    private final JPAQueryFactory jpaQueryFactory;
    private final SysConfigRepository sysConfigRepository;

    @Override
    public PageQryResult<SysConfig> getAllByPage(PageQryParam<SysConfig> pageQryParam) {
        SysConfig qParam = pageQryParam.getParam();
        QSysConfig qSysConfig = QSysConfig.sysConfig;

        Predicate predicate = qSysConfig.isNotNull().or(qSysConfig.isNull());
        if (null != qParam) {
            if (!StringUtils.isEmpty(qParam.getName())) {
                predicate = ExpressionUtils.and(predicate,
                        qSysConfig.name.contains(qParam.getName()));
            }
            if (!StringUtils.isEmpty(qParam.getUniqIdx())) {
                predicate = ExpressionUtils.and(predicate,
                        qSysConfig.uniqIdx.contains(qParam.getUniqIdx()));
            }
            if (null != qParam.getStatus()) {
                predicate = ExpressionUtils.and(predicate,
                        qSysConfig.status.eq(qParam.getStatus()));
            }
        }

        List<SysConfig> list = jpaQueryFactory.select(qSysConfig)
                .from(qSysConfig)
                .where(predicate).orderBy(qSysConfig.id.desc())
                .offset((pageQryParam.getPage() - 1) * pageQryParam.getSize())
                .limit(pageQryParam.getSize())
                .fetch();

        long total = Optional.ofNullable(jpaQueryFactory.select(qSysConfig.id.count())
                .from(qSysConfig)
                .where(predicate)
                .fetchOne()
        ).orElse(0L);

        return new PageQryResult<>(list, total);
    }

    @Override
    public SysConfig add(SysConfig sysConfig) {
        if (null != sysConfigRepository.findFirstByUniqIdx(sysConfig.getUniqIdx())) {
            throw new RuntimeException("配置索引已存在");
        }

        sysConfig.setCreateBy(LoginInfoAccessContext.getLoginInfo().getNickname());
        sysConfig.setUpdateBy(sysConfig.getUpdateBy());
        return sysConfigRepository.save(sysConfig);
    }

    @Override
    public SysConfig edit(SysConfig sysConfig) {

        SysConfig newSysConfig = sysConfigRepository.findFirstById(sysConfig.getId());
        if (null == newSysConfig) {
            throw new RuntimeException("404 NotFound");
        }

        if (null != sysConfigRepository.findFirstByUniqIdxAndIdNot(
                sysConfig.getUniqIdx(), newSysConfig.getId())) {
            throw new RuntimeException("配置索引已存在");
        }

        newSysConfig.edit(sysConfig);
        newSysConfig.setUpdateBy(LoginInfoAccessContext.getLoginInfo().getNickname());
        return sysConfigRepository.save(newSysConfig);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void del(List<Long> ids) {
        sysConfigRepository.deleteAllByIdInBatch(ids);
    }

    @Override
    public Object getConfig(String uniqIdx) {

        SysConfig sysConfig = sysConfigRepository.findFirstByUniqIdxAndStatus(uniqIdx, 1);

        if (null == sysConfig) {
            throw new RuntimeException("未找到配置索引");
        }

        if (StringUtils.isEmpty(sysConfig.getContent())) {
            throw new RuntimeException("未找到配置内容");
        }

        if (uniqIdx.equals("AliyunOss")) {
            return JSON.parseObject(sysConfig.getContent(), AliyunOssConfig.class);
        }

        if (uniqIdx.equals("MinioOss")) {
            return JSON.parseObject(sysConfig.getContent(), MinioOssConfig.class);
        }

        if (uniqIdx.equals("Pub")) {
            return JSON.parseObject(sysConfig.getContent(), PubConfig.class);
        }

        if (uniqIdx.equals("XxlJob")) {
            return JSON.parseObject(sysConfig.getContent(), XxlJobConfig.class);
        }

        throw new RuntimeException("未找到目标配置");
    }
}
